package com.yanqu.road.server.gameplayer.module.kuang;

import com.alibaba.fastjson.JSON;
import com.google.protobuf.AbstractMessage;
import com.yanqu.road.entity.config.system.PropertyWeightItem;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.enums.kuang.eKuangAttributeType;
import com.yanqu.road.entity.kuang.KuangConfig;
import com.yanqu.road.entity.kuang.KuangEquipmentData;
import com.yanqu.road.entity.kuang.KuangRankRewardConfig;
import com.yanqu.road.entity.kuang.KuangUserData;
import com.yanqu.road.entity.kuang.config.KuangSystemConfig;
import com.yanqu.road.entity.kuang.group.KuangMatchGroup;
import com.yanqu.road.entity.kuang.log.LogKuangEquipmentData;
import com.yanqu.road.entity.log.LogKuangDrawEquipment;
import com.yanqu.road.entity.log.LogKuangEquipEquipment;
import com.yanqu.road.entity.manor.ManorHarvestData;
import com.yanqu.road.entity.messageSubscribe.entity.MessageUserNoticeData;
import com.yanqu.road.entity.player.UserBagItem;
import com.yanqu.road.entity.player.UserPatrons;
import com.yanqu.road.entity.task.TaskConditionInfo;
import com.yanqu.road.entity.task.TaskInfo;
import com.yanqu.road.entity.task.UserTaskData;
import com.yanqu.road.logic.bussiness.kuang.KuangBusiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.rank.RankListModel;
import com.yanqu.road.pb.kuang.Kuang;
import com.yanqu.road.pb.rank.RankProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.BagModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.gameplayer.module.player.DecorationModule;
import com.yanqu.road.server.gameplayer.module.player.PreReduceModule;
import com.yanqu.road.server.gameplayer.module.task.TaskModule;
import com.yanqu.road.server.logic.mail.MailManager;
import com.yanqu.road.server.logic.task.BaseTaskData;
import com.yanqu.road.server.manger.MultipleLanguageMgr;
import com.yanqu.road.server.manger.activity.curio.CurioMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.config.TaskMgr;
import com.yanqu.road.server.manger.kuang.KuangMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.messagesubscribe.MessageSubscribeMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.manger.rank.RankMgr;
import com.yanqu.road.server.pb.KuangPb;
import com.yanqu.road.server.pb.PlayerPb;
import com.yanqu.road.server.protocol.CrossProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 矿场争夺战
 */
public class KuangModule extends GeneralModule {

    /**
     * 用户数据
     */
    private KuangUserData userData;

    private static RandomHelper randomHelper = new RandomHelper();


    public KuangModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        userData = KuangBusiness.getKuangUserData(player.getUserId());
        return true;
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public boolean saveData() {
        if (userData != null) {
            if (userData.isInsertOption()) {
                KuangBusiness.addKuangUserData(userData);
            } else if (userData.isUpdateOption()) {
                KuangBusiness.updateKuangUserData(userData);
            }
        }
        return true;
    }

    @Override
    public void afterLogin() {
        initSystem();
    }

    public void initSystem() {
        if (!SystemOpenMgr.systemOpen(player, eSystemId.Kuang.getValue())) {
            return;
        }
        // 检测是否需要重置、回收、补发(跨周)
        if (userData != null && userData.getWeekId() != GameConfig.getSystemThisWeekId()) {
            // 成就重置、补发
            resetKuangAchieve();

            // 回收开宝库道具
            Property cost = KuangMgr.getConfig().getKuangSystemConfig().getLotteryCost();
            if (cost != null) {
                for (Integer goodsId : cost.getGoods().keySet()) {
                    UserBagItem userBagItem = player.getModule(BagModule.class).getUserBagItem(goodsId);
                    if (userBagItem != null && userBagItem.getNum() > 0) {
                        player.getModule(CurrencyModule.class).removeCurrency(new Property(userBagItem.getGoodsId(), userBagItem.getNum()), eLogMoneyType.Kuang, eLogMoneyType.KuangRecycle);
                    }
                }
            }
        }
        // 初始化用户信息
        initUserData();

        // 检查分组变动
        checkGroupChange();

        // 计算玩家属性
        calcAttribute();

        // 同步下属性到活动跨服
        uploadAttributeToCross();

        // 同步下配置
        syncConfig();

        // 跨服拉一下活动状态
        crossLoginSync();

        // 设置微信推送时间
        try {
            MessageSubscribePushTime();
        }catch (Exception e){
            log.error("error:" + e);
        }
    }

    /**
     * 设置推送时间
     */
    private void MessageSubscribePushTime(){
        if(!MessageSubscribeMgr.isSwitch()){
            return;
        }
        List<Long> timeList = new ArrayList<>();
        KuangConfig config = KuangMgr.getConfig();
        if (config == null || config.getTimeConfig() == null) {
            return;
        }
        // 策划要求写死的提前时间 5 分钟
        long preTime = 5 * 60 * DateHelper.SECOND_MILLIONS;
        long day1 = config.getTimeConfig().getDay1BattleStartTime() - preTime;
        long day2 = config.getTimeConfig().getDay2BattleStartTime() - preTime;
        timeList.add(day1);
        timeList.add(day2);
        MessageUserNoticeData noticeData = MessageSubscribeMgr.getUserNoticeData(player.getUserId());
        noticeData.setSubTime(eMessageSubscribeType.KuangBattleTime, timeList);
    }

    /**
     * 同步配置
     */
    private void syncConfig() {
        if (!SystemOpenMgr.systemOpen(player, eSystemId.Kuang.getValue())) {
            return;
        }
        KuangMatchGroup matchGroup = KuangMgr.getMatchGroup();
        if (matchGroup == null) {
            // 没有分组不初始化
            return;
        }
        KuangConfig config = KuangMgr.getConfig();
        if (config == null) {
            return;
        }
        KuangSystemConfig kuangSystemConfig = config.getKuangSystemConfig();
        if (kuangSystemConfig == null) {
            return;
        }
        // 最小开服天数
        int openDay = matchGroup.getOpenDay();
        Kuang.KuangSystemConfigSyncMsg.Builder builder = Kuang.KuangSystemConfigSyncMsg.newBuilder();
        for (KuangRankRewardConfig rankRewardConfig : kuangSystemConfig.getPersonRankRewardConfig(openDay)) {
            builder.addPersonRankReward(KuangPb.parseKuangRankRewardTemp(rankRewardConfig));
        }
        for (KuangRankRewardConfig rankRewardConfig : kuangSystemConfig.getGroupRankRewardConfig(openDay)) {
            builder.addGroupRankReward(KuangPb.parseKuangRankRewardTemp(rankRewardConfig));
        }
        for (PropertyWeightItem weightItem : kuangSystemConfig.getLotteryGeneraReward(openDay)) {
            builder.addGeneraReward(KuangPb.parseKuangLotteryRewardTemp(weightItem));
        }
        for (PropertyWeightItem weightItem : kuangSystemConfig.getLotterySpecialReward(openDay)) {
            builder.addSpecialReward(KuangPb.parseKuangLotteryRewardTemp(weightItem));
        }
        builder.setLotteryCost(PropertyHelper.parsePropertyToString(kuangSystemConfig.getLotteryCost()));
        builder.setLotteryBoxNum(kuangSystemConfig.getLotteryBoxNum());
        player.sendPacket(Protocol.U_KUANG_CONFIG_SYNC, builder);
    }

    /**
     * 每日0点
     */
    public void resetOneDay() {
        // 处理一下数据
        initSystem();
    }

    /**
     * 检查分组变动
     */
    private void checkGroupChange() {
        KuangMatchGroup matchGroup = KuangMgr.getMatchGroup();
        if (matchGroup == null) {
            // 没有分组不初始化
            return;
        }
        if (userData == null) {
            return;
        }

        if (userData.getWeekId() != matchGroup.getWeekId() || userData.getGroupId() != matchGroup.getGroupId()) {
            // 重置
            userData = new KuangUserData();
            userData.setUserId(player.getUserId());
            userData.setWeekId(matchGroup.getWeekId());
            userData.setGroupId(matchGroup.getGroupId());
            userData.setDrawTimes(0);
            userData.setTotalDrawTimes(0);
            userData.setChooseEquipmentDataList(new ArrayList<>());
            userData.setEquipmentDataMap(new ConcurrentHashMap<>());
            userData.setAttributeMap(new ConcurrentHashMap<>());
            userData.setLastRoundScore(0);

            // 重置后重新计算下属性
            calcAttribute();
        }
    }

    /**
     * 重置矿场成就
     */
    public void resetKuangAchieve() {
        // 获取未领取奖励
//        Property reward = new Property();
        Map<Integer, BaseTaskData> baseTaskDataMap = player.getModule(TaskModule.class).getBaseTaskDataMap();
        for (BaseTaskData baseTaskData : baseTaskDataMap.values()) {
            UserTaskData userTaskData = baseTaskData.getUserTaskData();
            if (userTaskData == null) {
                continue;
            }
            if (userTaskData.getTaskType() == eTaskType.Kuang.getValue()) {
                // 未领奖
                if (userTaskData.getState() == 0) {
//                    TaskConditionInfo taskConditionInfo = baseTaskData.getBaseCondition().getTaskConditionInfo();
//                    TaskInfo taskInfo = TaskMgr.getTaskInfoById(taskConditionInfo.getTaskId());
                    // 能完成
                    if (baseTaskData.canCompleted()) {
                        userTaskData.setState(1); // 虽然马上要重置了但还是设置下状态比较稳
                        userTaskData.setFinishTime(System.currentTimeMillis() / 1000);
//                        reward.addProperty(taskInfo.getReward());
                    }
                }
            }
        }
        // 发奖(策划说不补发了)
//        if (!reward.isNothing()) {
//            String mailTitle = MultipleLanguageMgr.getContent(MailManager.KUANG_ACHIEVE_REWARD_TITLE, player.getLanguage());
//            String mailContent = MultipleLanguageMgr.getContent(MailManager.KUANG_ACHIEVE_REWARD_CONTENT, player.getLanguage());
//            MailManager.sendMailOnLoad(player, eMailType.SYSTEM.getValue(), PropertyHelper.parsePropertyToString(reward), mailContent, mailTitle);
//        }

        // 重置
        player.getModule(TaskModule.class).resetKuangAchieve();

    }

    private void crossLoginSync() {
        if (userData == null) {
            return;
        }
        int matchGroupId = KuangMgr.getMatchGroupId();
        if (matchGroupId == -1) {
            return;
        }
        // 去跨服拿下活动状态
        Kuang.CrossKuangLoginSyncMsg.Builder builder = Kuang.CrossKuangLoginSyncMsg.newBuilder();
        builder.setGroupId(matchGroupId);
        builder.setUserBaseInfo(PlayerPb.parsePlayerBaseTempMsg(player.getUserInfo()));
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_LOGIN_SYNC, builder);
    }

    private synchronized void initUserData() {
        if (userData != null) {
            return;
        }
        KuangMatchGroup matchGroup = KuangMgr.getMatchGroup();
        if (matchGroup == null) {
            return;
        }
        userData = new KuangUserData();
        userData.setUserId(player.getUserId());
        userData.setWeekId(matchGroup.getWeekId());
        userData.setGroupId(matchGroup.getGroupId());
        userData.setDrawTimes(0);
        userData.setTotalDrawTimes(0);
        userData.setChooseEquipmentDataList(new ArrayList<>());
        userData.setEquipmentDataMap(new ConcurrentHashMap<>());
        userData.setAttributeMap(new ConcurrentHashMap<>());
        userData.setInsertOption();
    }

    public void syncUserData() {
        if (userData == null) {
            return;
        }
        Kuang.KuangUserDataSyncMsg.Builder syncMsg = Kuang.KuangUserDataSyncMsg.newBuilder();
        syncMsg.setUserData(KuangPb.parseKuangUserDataTemp(userData));
        player.sendPacket(Protocol.U_KUANG_USER_DATA_SYNC, syncMsg);
    }

    /**
     * 抽装备
     */
    public int drawEquipment() {
        KuangConfig config = KuangMgr.getConfig();
        if (config == null) {
            return GameErrorCode.E_KUANG_CONFIG_NOT_FOUND;
        }
        if (!config.isActivityTime()){
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        if (userData == null) {
            return GameErrorCode.E_KUANG_SYSTEM_NOT_OPEN;
        }
        KuangMatchGroup matchGroup = KuangMgr.getMatchGroup();
        if (matchGroup == null) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        if (userData.getDrawTimes() > 0) {
            userData.setDrawTimes(userData.getDrawTimes() - 1);
        } else {
            // 次数不足，判断消耗
            // 判断消耗
            Property cost = PropertyHelper.parseStringToProperty(GameConfig.KUANG_EQUIPMENT_COST);
            if (!player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.Kuang, eLogMoneyType.KuangDrawCost)) {
                return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
            }
        }
        // 清空下
        userData.getChooseEquipmentDataList().clear();
        for (int i = 0; i < KuangConfig.MAX_DRAW_EQUIPMENT_CNT; i++) {
            int quality = KuangMgr.drawQuality(userData.getTotalDrawTimes());
            if (quality == -1) {
                continue;
            }
            int equipId = KuangMgr.drawEquip(quality);
            // 生成装备属性
            KuangEquipmentData equipmentData = KuangMgr.initEquipmentData(equipId);
            userData.getChooseEquipmentDataList().add(equipmentData);
        }
        userData.setTotalDrawTimes(userData.getTotalDrawTimes() + 1);
        userData.setUpdateOption();
        Kuang.KuangDrawEquipmentRespMsg.Builder respMsg = Kuang.KuangDrawEquipmentRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setUserData(KuangPb.parseKuangUserDataTemp(userData));
        player.sendPacket(Protocol.U_KUANG_DRAW_EQUIPMENT, respMsg);

        List<LogKuangEquipmentData> logKuangEquipmentDataList = new ArrayList<>();
        for (KuangEquipmentData equipmentData : userData.getChooseEquipmentDataList()) {
            logKuangEquipmentDataList.add(getLogKuangEquipmentData(equipmentData));
        }

        // 日志
        AutoLogMgr.add(new LogKuangDrawEquipment(
                matchGroup.getWeekId(),
                matchGroup.getGroupId(),
                player.getUserId(),
                JSON.toJSONString(logKuangEquipmentDataList)
        ));
        return 0;
    }

    public LogKuangEquipmentData getLogKuangEquipmentData(KuangEquipmentData equipmentData) {
        LogKuangEquipmentData logKuangEquipmentData = new LogKuangEquipmentData();
        logKuangEquipmentData.setEquipmentId(equipmentData.getEquipmentId());
        logKuangEquipmentData.setTotalAttributeMap(new ConcurrentHashMap<>(equipmentData.getTotalAttributeMap()));
        return logKuangEquipmentData;
    }

    /**
     * 放弃当前的装备池
     */
    public int giveUpChooseEquipment() {
        KuangConfig config = KuangMgr.getConfig();
        if (config == null) {
            return GameErrorCode.E_KUANG_CONFIG_NOT_FOUND;
        }
        if (!config.isActivityTime()){
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        if (userData == null) {
            return GameErrorCode.E_KUANG_SYSTEM_NOT_OPEN;
        }
        if (userData.getChooseEquipmentDataList().isEmpty()) {
            return GameErrorCode.E_KUANG_NO_CHOOSE_EQUIPMENT;
        }
        userData.getChooseEquipmentDataList().clear();
        userData.setUpdateOption();
        Kuang.KuangGiveUpChooseEquipmentRespMsg.Builder respMsg = Kuang.KuangGiveUpChooseEquipmentRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setUserData(KuangPb.parseKuangUserDataTemp(userData));
        player.sendPacket(Protocol.U_KUANG_GIVE_UP_CHOOSE_EQUIPMENT, respMsg);
        return 0;
    }

    /**
     * 穿装备
     */
    public int equipEquipment(int type, int chooseIdx) {
        KuangConfig config = KuangMgr.getConfig();
        if (config == null) {
            return GameErrorCode.E_KUANG_CONFIG_NOT_FOUND;
        }
        if (!config.isActivityTime()){
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        if (userData == null) {
            return GameErrorCode.E_KUANG_SYSTEM_NOT_OPEN;
        }
        KuangMatchGroup matchGroup = KuangMgr.getMatchGroup();
        if (matchGroup == null) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        if (chooseIdx < 0 || chooseIdx >= userData.getChooseEquipmentDataList().size()) {
            return GameErrorCode.E_KUANG_PARAM_ERROR;
        }
        if (userData.getChooseEquipmentDataList().isEmpty()) {
            return GameErrorCode.E_KUANG_PARAM_ERROR;
        }
        KuangEquipmentData equipmentData = userData.getChooseEquipmentDataList().get(chooseIdx);
        if (equipmentData == null) {
            return GameErrorCode.E_KUANG_PARAM_ERROR;
        }
        if (equipmentData.getType() != type) {
            return GameErrorCode.E_KUANG_PARAM_ERROR;
        }
        userData.getEquipmentDataMap().put(type, equipmentData);
        userData.getChooseEquipmentDataList().clear();
        // 计算玩家属性
        calcAttribute();
        // 上传一下属性到跨服
        uploadAttributeToCross();

        userData.setUpdateOption();
        Kuang.KuangEquipEquipmentRespMsg.Builder respMsg = Kuang.KuangEquipEquipmentRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setUserData(KuangPb.parseKuangUserDataTemp(userData));
        player.sendPacket(Protocol.U_KUANG_EQUIP_EQUIPMENT, respMsg);

        // 身上的装备
        List<LogKuangEquipmentData> logKuangEquipmentDataList = new ArrayList<>();
        for (KuangEquipmentData kuangEquipmentData : userData.getEquipmentDataMap().values()) {
            logKuangEquipmentDataList.add(getLogKuangEquipmentData(kuangEquipmentData));
        }
        // 记录日志
        AutoLogMgr.add(new LogKuangEquipEquipment(
                matchGroup.getWeekId(),
                matchGroup.getGroupId(),
                player.getUserId(),
                JSON.toJSONString(getLogKuangEquipmentData(equipmentData)),
                JSON.toJSONString(logKuangEquipmentDataList)
        ));
        return 0;
    }

    /**
     * 计算属性值
     */
    public void calcAttribute() {
        if (userData == null) {
            return;
        }
        Map<eKuangAttributeType, Long> attributeMap = new ConcurrentHashMap<>();
        // 基础属性
        List<Integer> fightTurnParamList = StringUtils.stringToIntegerList(GameConfig.KUANG_FIGHT_TURN_PARAM, "\\|");
        // 赚钱
        BigDecimal x = BigDecimal.valueOf(player.getUserInfo().getTotalAbility().longValue()).divide(BigDecimal.valueOf(100000000), 3, RoundingMode.UP);
        BigDecimal t1 = BigDecimal.valueOf(fightTurnParamList.get(0)).divide(BigDecimal.valueOf(1000), 8, RoundingMode.UP);
        BigDecimal t2 = BigDecimal.valueOf(fightTurnParamList.get(1)).divide(BigDecimal.valueOf(1000), 8, RoundingMode.UP);
        BigDecimal t3 = BigDecimal.valueOf(fightTurnParamList.get(2)).divide(BigDecimal.valueOf(1000), 8, RoundingMode.UP);
        double t4 = Math.pow(x.doubleValue(), t2.doubleValue());
        // 裸战力
        long tempAbility = t1.multiply(BigDecimal.valueOf(t4)).add(t3).setScale(0, RoundingMode.UP).longValue();
        attributeMap.put(eKuangAttributeType.AttributeEnum_TempAbility, tempAbility);
        // 计算攻血
        List<Integer> fightTurnAttHpParamList = StringUtils.stringToIntegerList(GameConfig.KUANG_FIGHT_TURN_ATTHP_PARAM, "\\|");
        BigDecimal p1 = BigDecimal.valueOf(fightTurnAttHpParamList.get(0)).divide(BigDecimal.valueOf(1000), 8, RoundingMode.UP);
        BigDecimal p2 = BigDecimal.valueOf(fightTurnAttHpParamList.get(1)).divide(BigDecimal.valueOf(1000), 8, RoundingMode.UP);
        BigDecimal p3 = BigDecimal.valueOf(fightTurnAttHpParamList.get(2)).divide(BigDecimal.valueOf(1000), 8, RoundingMode.UP);
        BigDecimal p4 = BigDecimal.valueOf(fightTurnAttHpParamList.get(3)).divide(BigDecimal.valueOf(1000), 8, RoundingMode.UP);

        // 攻击=裸战力^(参数1/1000)
        long attack = p4.multiply(BigDecimal.valueOf(Math.pow(tempAbility, p1.doubleValue()))).setScale(0, RoundingMode.UP).longValue();
        // 藏品加成
        attack += CurioMgr.getSkillAdditionBySkillType(eSkillType.KuangBattleAttackSkill.getValue(), player, 0);
        attributeMap.put(eKuangAttributeType.AttributeEnum_Attack, attack);
        // 血量=(参数3/1000)*裸战力^(参数2/1000)
        long hp = p3.multiply(BigDecimal.valueOf(Math.pow(tempAbility,p2.doubleValue()))).setScale(0, RoundingMode.UP).longValue();
        // 藏品加成
        hp += CurioMgr.getSkillAdditionBySkillType(eSkillType.KuangBattleHpSkill.getValue(), player, 0);
        attributeMap.put(eKuangAttributeType.AttributeEnum_Hp, hp);
        // 基础攻速
        attributeMap.put(eKuangAttributeType.AttributeEnum_AttackSpeed, (long) GameConfig.KUANG_BASE_ATTACK_SPEED);
        // 装备属性
        for (KuangEquipmentData equipmentData : userData.getEquipmentDataMap().values()) {
            for (Map.Entry<eKuangAttributeType, Long> entry : equipmentData.getTotalAttributeMap().entrySet()) {
                attributeMap.put(entry.getKey(), attributeMap.getOrDefault(entry.getKey(), 0L) + entry.getValue());
            }
        }
        // 检查属性值
        checkAttribute(attributeMap);
        // 统计下战力
        calcAbility(attributeMap);

        // 财神称号等级
        attributeMap.put(eKuangAttributeType.AttributeEnum_HonoraryTitleLevel, (long) player.getModule(DecorationModule.class).getUserMaxDecorationClass());

        userData.setAttributeMap(attributeMap);
    }

    /**
     * 计算战斗力
     *
     * @param attributeMap 属性列表
     */
    private void calcAbility(Map<eKuangAttributeType, Long> attributeMap) {
        KuangConfig config = KuangMgr.getConfig();
        if (config == null) {
            return;
        }
        List<Integer> paramList = config.getAbilityParamList();
        long ability = BigDecimal.valueOf(paramList.get(8)).divide(BigDecimal.valueOf(paramList.get(9)), 10, RoundingMode.UP)
                .multiply(BigDecimal.valueOf(attributeMap.getOrDefault(eKuangAttributeType.AttributeEnum_Attack, 0L)).multiply(BigDecimal.valueOf(attributeMap.getOrDefault(eKuangAttributeType.AttributeEnum_Hp, 0L))))
                .multiply(BigDecimal.valueOf(1).add(BigDecimal.valueOf(attributeMap.getOrDefault(eKuangAttributeType.AttributeEnum_EquipmentScore, 0L)).divide(BigDecimal.valueOf(paramList.get(7)), 8, RoundingMode.DOWN)))
                .setScale(0, RoundingMode.UP)
                .longValue();
        attributeMap.put(eKuangAttributeType.AttributeEnum_Ability, ability);
    }

    /**
     * 检查属性值
     * 属性范围 [0,maxValue]
     *
     * @param attributeMap 属性值
     */
    public void checkAttribute(Map<eKuangAttributeType, Long> attributeMap) {
        KuangConfig config = KuangMgr.getConfig();
        if (config == null) {
            return;
        }
        for (Map.Entry<eKuangAttributeType, Long> entry : config.getMaxAttributeMap().entrySet()) {
            eKuangAttributeType attributeType = entry.getKey();
            attributeMap.put(attributeType, Math.max(0, Math.min(entry.getValue(), attributeMap.getOrDefault(attributeType, 0L))));
        }
    }

    public boolean hasGroup(){
        KuangConfig config = KuangMgr.getConfig();
        if (config == null) {
            return false;
        }
        if (userData == null) {
            return false;
        }
        // 没有分组也不能打
        KuangMatchGroup group = KuangMgr.getMatchGroup();
        if (group == null) {
            return false;
        }
        // 战斗时间上跨服判断
        return true;
    }


    /**
     * 进入pvp
     */
    public int enterBattle() {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        // 进入时算下属性
        calcAttribute();
        // 发到跨服拿数据
        Kuang.CrossKuangBattleEnterReqMsg.Builder builder = Kuang.CrossKuangBattleEnterReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        // 玩家属性
        for (Map.Entry<eKuangAttributeType, Long> entry : userData.getAttributeMap().entrySet()) {
            Kuang.AttributeDataTemp.Builder attributeDataTemp = KuangPb.parseAttributeDataTemp(entry.getKey(), entry.getValue());
            if (attributeDataTemp != null) {
                builder.addAttribute(attributeDataTemp);
            }
        }
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_ENTER_BATTLE, builder);
        userData.setUpdateOption();
        return 0;
    }


    /**
     * 进入房间
     */
    public int enterPlace(int placeId) {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        // 发到跨服拿数据
        Kuang.CrossKuangBattleEnterPlaceReqMsg.Builder builder = Kuang.CrossKuangBattleEnterPlaceReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        builder.setPlaceId(placeId);
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_ENTER_PLACE, builder);
        return 0;
    }

    /**
     * 进入pvp
     */
    public int leavePlace() {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        // 发到跨服拿数据
        Kuang.CrossKuangBattleLeavePlaceReqMsg.Builder builder = Kuang.CrossKuangBattleLeavePlaceReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_LEAVE_PLACE, builder);
        return 0;
    }

    public int battleMove(Kuang.KuangBattlePositionTemp positionTemp) {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        // 发到跨服拿数据
        Kuang.CrossKuangBattleMoveReqMsg.Builder builder = Kuang.CrossKuangBattleMoveReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        builder.setPosition(positionTemp);
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_BATTLE_MOVE, builder);
        return 0;
    }

    /**
     * 攻击
     */
    public int battleAttack(long attackUserId) {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        // 发到跨服拿数据
        Kuang.CrossKuangBattleAttackReqMsg.Builder builder = Kuang.CrossKuangBattleAttackReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        builder.setAttackUserId(attackUserId);
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_BATTLE_ATTACK, builder);
        return 0;
    }

    /**
     * 看聊天
     */
    public int getKuangChatList(List<Integer> paramList) {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        if (paramList.isEmpty()) {
            return GameErrorCode.E_KUANG_PARAM_ERROR;
        }
        // 发到跨服拿数据
        Kuang.CrossKuangChatListReqToCrossMsg.Builder builder = Kuang.CrossKuangChatListReqToCrossMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        builder.addAllParam(paramList);
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_GET_CHAT, builder);
        return 0;
    }

    /**
     * 获取房间信息
     */
    public int getBattlePlaceData() {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        // 发到跨服拿数据
        Kuang.CrossKuangBattleGetPlaceInfoReqMsg.Builder builder = Kuang.CrossKuangBattleGetPlaceInfoReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_BATTLE_GET_PLACE_DATA, builder);
        return 0;
    }

    /**
     * 获取宗门信息列表
     */
    public int getBattleCampUserList(int campId) {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        // 发到跨服拿数据
        Kuang.CrossKuangBattleGetCampUserListReqMsg.Builder builder = Kuang.CrossKuangBattleGetCampUserListReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        builder.setCampId(campId);
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_BATTLE_GET_CAMP_USER_LIST, builder);
        return 0;
    }

    public int getMaxAbilityUser() {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        // 发到跨服拿数据
        Kuang.CrossKuangBattleGetMajorUserReqMsg.Builder builder = Kuang.CrossKuangBattleGetMajorUserReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_GET_MAJOR_USER, builder);
        return 0;
    }


    public int getCampServer() {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        // 发到跨服拿数据
        Kuang.CrossKuangBattleGetCampServerReqMsg.Builder builder = Kuang.CrossKuangBattleGetCampServerReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_GET_CAMP_SERVER, builder);
        return 0;
    }


    public int appointMinorUser(long minorUserId) {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        // 发到跨服拿数据
        Kuang.CrossKuangBattleAppointMinorUserReqMsg.Builder builder = Kuang.CrossKuangBattleAppointMinorUserReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        builder.setMinorUserId(minorUserId);
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_APPOINT_MINOR_USER, builder);
        return 0;
    }

    public int markPlace(int placeId) {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        // 发到跨服拿数据
        Kuang.CrossKuangBattleMarkPlaceReqMsg.Builder builder = Kuang.CrossKuangBattleMarkPlaceReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        builder.setPlaceId(placeId);
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_MARK_PLACE, builder);
        return 0;
    }

    public int leaveBattle() {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        // 发到跨服拿数据
        Kuang.CrossKuangBattleLeaveReqMsg.Builder builder = Kuang.CrossKuangBattleLeaveReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_LEAVE_BATTLE, builder);
        return 0;
    }

    public int getBattleReport(long targetUserId) {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        // 发到跨服拿数据
        Kuang.CrossKuangBattleGetReportReqMsg.Builder builder = Kuang.CrossKuangBattleGetReportReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        builder.setUserId(targetUserId);
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_GET_BATTLE_REPORT, builder);
        return 0;
    }

    public int getBattleEndData() {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        // 发到跨服拿数据
        Kuang.CrossKuangGetBattleEndDataReqMsg.Builder builder = Kuang.CrossKuangGetBattleEndDataReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_GET_BATTLE_END_DATA, builder);
        return 0;
    }

    public int useSkill(int type, int littleType) {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        // 发到跨服拿数据
        Kuang.CrossKuangBattleUseSkillReqMsg.Builder builder = Kuang.CrossKuangBattleUseSkillReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        builder.setType(type);
        builder.setLittleType(littleType);
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_BATTLE_USE_SKILL, builder);
        return 0;
    }

    public int endDataLike(int round, int type) {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        // 发到跨服拿数据
        Kuang.CrossKuangBattleEndDataLikeReqMsg.Builder builder = Kuang.CrossKuangBattleEndDataLikeReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        builder.setRound(round);
        builder.setType(type);
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_END_DATA_LIKE, builder);
        return 0;
    }

    public int getUserRankList(int type, String param) {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        // 发到跨服拿数据
        Kuang.CrossKuangBattleGetUserRankReqMsg.Builder builder = Kuang.CrossKuangBattleGetUserRankReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        builder.setType(type);
        builder.setParam(param);
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_GET_USER_RANK_LIST, builder);
        return 0;
    }

    public int getCampRankList() {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        // 发到跨服拿数据
        Kuang.CrossKuangBattleGetCampRankReqMsg.Builder builder = Kuang.CrossKuangBattleGetCampRankReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_GET_CAMP_RANK_LIST, builder);
        return 0;
    }

    public int getCampScoreRecord(int campId) {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        // 发到跨服拿数据
        Kuang.CrossKuangBattleGetCampScoreRecordReqMsg.Builder builder = Kuang.CrossKuangBattleGetCampScoreRecordReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        builder.setCampId(campId);
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_GET_CAMP_SCORE_RECORD, builder);
        return 0;
    }

    public void getUserAbilityRank(long targetServerId) {
        if (!hasGroup()) {
            return;
        }
        if (targetServerId == GameServer.getInstance().getServerId()) {
            Kuang.KuangUserAbilityRankListRespMsg.Builder builder = Kuang.KuangUserAbilityRankListRespMsg.newBuilder();
            RankProto.RankListMsg.Builder rankListMsg;
            // 本服赚钱榜
            RankListModel rankListModel = RankMgr.getRankListModelByType(eBigRankType.Normal.getValue(), eRankType.PatronsAbility.getValue());
            if (null != rankListModel) {
                rankListMsg = rankListModel.getRankListMsg();
                builder.setMyRank(rankListModel.unlockGetMyRank(player.getUserId()));
            } else {
                rankListMsg = RankProto.RankListMsg.newBuilder();
                builder.setMyRank(-1);
            }
            builder.setRankList(rankListMsg);
            player.sendPacket(Protocol.U_KUANG_GET_USER_ABILITY_RANK, builder);
        } else {
            // 发到跨服拿数据
            Kuang.CrossKuangUserAbilityRankListReqMsg.Builder builder = Kuang.CrossKuangUserAbilityRankListReqMsg.newBuilder();
            builder.setGroupId(KuangMgr.getMatchGroupId());
            builder.setTargetServerId(targetServerId);
            sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_GET_USER_ABILITY, builder);
        }
    }


    /**
     * 发送到活动跨服
     */
    public void sendAppointActivityPacket(int code, AbstractMessage.Builder<?> messageBuilder) {
        KuangMatchGroup matchGroup = KuangMgr.getMatchGroup();
        if (matchGroup == null) {
            return;
        }
        GamePlayerMgr.sendAppointActivityPacket(code, messageBuilder, player.getUserId(), matchGroup.getCrossId());
    }

    public KuangUserData getUserData() {
        return userData;
    }

    public void loginFromCross(Kuang.CrossKuangLoginRespMsg reqMsg) {
        if (userData == null) {
            return;
        }
        // 检查下分组
        checkGroupChange();
        if (userData.getWeekId() != reqMsg.getWeekId() || userData.getGroupId() != reqMsg.getGroupId()) {
            log.error("loginFromCross weekId or groupId error!");
            return;
        }
        // 轮次重置
        if (reqMsg.getRoundDay() != userData.getRoundDay()) {
            userData.setRoundDay(reqMsg.getRoundDay());
//            userData.setDrawTimes(0);
            // 基础次数
            userData.setDrawTimes(userData.getDrawTimes() + KuangMgr.getMaxDrawTimes(userData.getRoundDay()));
            userData.setLastRoundScore(reqMsg.getFirstRoundScore());
            // 计算额外次数
            if (userData.getRoundDay() == 2) {
                List<String> exList = StringUtils.stringToStringList(GameConfig.KUANG_EQUIPMENT_DRAW_NUM_EX, "\\|");
                int addCnt = 0;
                for (String s : exList) {
                    String[] split = s.split(";");
                    if (userData.getLastRoundScore() >= Long.parseLong(split[0])) {
                        addCnt = Integer.parseInt(split[1]);
                    }
                }
                userData.setDrawTimes(userData.getDrawTimes() + addCnt);
            }
            if(reqMsg.getRoundDay() == 1){
                int initTimes = (int)CurioMgr.getSkillAdditionBySkillType(eSkillType.KuangBattleBuildTimesSkill.getValue(), player, 0);
                userData.setCurioTimes(initTimes);
                userData.setDrawTimes(initTimes + KuangMgr.getMaxDrawTimes(userData.getRoundDay()));
            }
        }
        if (reqMsg.getCampId() != userData.getCampId()) {
            userData.setCampId(reqMsg.getCampId());
        }
        // 同步用户数据
        syncUserData();

        // 同步下状态
        Kuang.KuangBattleStateSync.Builder builder = Kuang.KuangBattleStateSync.newBuilder();
        builder.setWeekId(reqMsg.getWeekId());
        builder.setBattleEnd(reqMsg.getBattleEnd());
        builder.setPersonRankReward(reqMsg.getPersonRankReward());
        builder.setGroupRankReward(reqMsg.getGroupRankReward());
        builder.setEnterBattle(reqMsg.getEnterBattle());
        player.sendPacket(Protocol.U_KUANG_BATTLE_STATE_SYNC, builder);
    }


    public int getTreasureData() {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        // 上跨服
        Kuang.CrossKuangGetTreasureDataReqMsg.Builder builder = Kuang.CrossKuangGetTreasureDataReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_GET_TREASURE_DATA, builder);
        return 0;
    }

    public int chooseTreasure(int position) {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        KuangConfig config = KuangMgr.getConfig();
        if (config == null || config.getKuangSystemConfig() == null) {
            return GameErrorCode.E_KUANG_CONFIG_NOT_FOUND;
        }
        Property property = config.getKuangSystemConfig().getLotteryCost();
        if(!player.getModule(CurrencyModule.class).currencyIsEnough(property)){
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }
        // 预扣除
        player.getModule(PreReduceModule.class).preReduce(property);
        // 上跨服
        Kuang.CrossKuangChooseTreasureReqMsg.Builder builder = Kuang.CrossKuangChooseTreasureReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        builder.setPosition(position);
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_CHOOSE_TREASURE, builder);
        return 0;
    }

    public int getRankReward(int type) {
        if (!hasGroup()) {
            return GameErrorCode.E_KUANG_BATTLE_NOT_OPEN;
        }
        // 上跨服
        Kuang.CrossKuangGetRankRewardReqMsg.Builder builder = Kuang.CrossKuangGetRankRewardReqMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        builder.setType(type);
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_GET_RANK_REWARD, builder);
        return 0;
    }

    /**
     * 门客赚钱变动
     */
    public void patronsAbilityChange() {
        if (!SystemOpenMgr.systemOpen(player, eSystemId.Kuang.getValue())) {
            return;
        }
        if (userData == null) {
            return;
        }
        KuangMatchGroup matchGroup = KuangMgr.getMatchGroup();
        if (matchGroup == null) {
            // 没有分组不初始化
            return;
        }
        // 重新计算属性
        calcAttribute();
        // 同步用户数据
        syncUserData();

        // 加到待同步到跨服列表
        KuangMgr.addUploadAttributeUserId(player.getUserId());
    }

    /**
     * 上传属性到跨服
     */
    public void uploadAttributeToCross() {
        if (!SystemOpenMgr.systemOpen(player, eSystemId.Kuang.getValue())) {
            return;
        }
        if (userData == null) {
            return;
        }
        KuangMatchGroup matchGroup = KuangMgr.getMatchGroup();
        if (matchGroup == null) {
            // 没有分组不初始化
            return;
        }
        Kuang.CrossKuangUploadAttributeMsg.Builder builder = Kuang.CrossKuangUploadAttributeMsg.newBuilder();
        builder.setGroupId(KuangMgr.getMatchGroupId());
        // 玩家属性
        for (Map.Entry<eKuangAttributeType, Long> entry : userData.getAttributeMap().entrySet()) {
            Kuang.AttributeDataTemp.Builder attributeDataTemp = KuangPb.parseAttributeDataTemp(entry.getKey(), entry.getValue());
            if (attributeDataTemp != null) {
                builder.addAttribute(attributeDataTemp);
            }
        }
        sendAppointActivityPacket(CrossProtocol.C_CROSS_KUANG_UPLOAD_ATTRIBUTE, builder);
    }
}
